import java.util.Arrays;
import java.util.Random;

public class Evolve extends Data {
	static Random R;
	static State[] E; // SELECTED TO EVOLVE
	static State[] P; // POPULATION

	static void init() {
//		FakeData.fakeData();
		Data.tryRead();

		R = new Random(2);
		P = new State[10];
		E = new State[2];

		for (int p = 0; p < P.length; p++) {
			P[p] = new State();
			for (int c = 0; c < Data.COLS; c++) {
				P[p].weight[c] = R.nextDouble();
			}
		}
	}

	public static void main(String[] args) {
		init();

		while (true) {
			step();
			echoBest();
		}
	}

	static void step() {
		parentSelection();
		evolveSelected();
		calculateFitness();
		Arrays.sort(P);
		replaceBottom();
	}

	static void parentSelection() {
		for (int e = 0; e < E.length; e++) {
			int i = R.nextInt(P.length);
			E[e] = P[i].clone();
		}
	}

	static void evolveSelected() {
		for (int e = 0; e < E.length; e++) {
			E[e].backpropegation();
//			E[e].numberOfWeightsToEvolve += R.nextGaussian();
//
//			double N = Math.abs(E[e].numberOfWeightsToEvolve);
//			for (int n = 0; n < N; n++) {
//				int c = R.nextInt(COLS);
//				E[e].sigma[c] += R.nextGaussian();
//				E[e].weight[c] += E[e].sigma[c] * R.nextGaussian();
//			}
		}
	}

	static void calculateFitness() {
		for (State s : E) {
			s.setError();
		}
	}

	static void replaceBottom() {
		for (int e = 0; e < E.length; e++) {
			P[P.length - 1 - e] = E[e];
		}
	}

	static void echoBest() {
		if (FakeData.FORMULA != null) {
			System.out.print("f: \t");
			for (int c = 0; c < COLS; c++) {
				System.out.printf("%+05.2f \t", FakeData.FORMULA[c]);
			}
			System.out.println();
		}

		System.out.print("w: \t");
		for (int c = 0; c < COLS; c++) {
			System.out.printf("%+05.2f \t", P[0].weight[c]);
		}
		System.out.println();
		System.out.print("s: \t");
		for (int c = 0; c < COLS; c++) {
			System.out.printf("%+05.2f \t", P[0].sigma[c]);
		}
		System.out.println();
		System.out.printf("%+5.5f \t", P[0].error);
		System.out.printf("nowte: %+5.5f", P[0].numberOfWeightsToEvolve);
		System.out.println();
		System.out.println();
	}
}
